# encoding=utf8
# noinspection PyBroadException
import sys
import datetime
import os
import subprocess
from flask import Flask, render_template, request, redirect, url_for, json, jsonify
from flask_cors import CORS
from modes import db, Hosts, projects, DeployTask, Node, Logs, scTemp
from gitclone import git
# from repo import GitRepository
from utils import Codezip
from sqlalchemy import or_, and_
from sshclient import SSHProxy

# sys.setdefaultencoding('utf-8')
# reload(sys)

app = Flask(__name__)
db.init_app(app)
CORS(app)
app.config['SECRET_KEY'] = os.urandom(24)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@127.0.0.1:3306/smartssh'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
date = datetime.datetime.now().strftime('%Y%m%d%H')
print(date)


@app.route('/')
def hello_world():
    db.create_all()
    return render_template('server.html')


@app.route('/list')
def list():
    hostlist = Hosts.query.all()
    print(hostlist)
    return render_template('server.html', hostlist=hostlist)


@app.route('/status/<int:id>', methods=['GET', 'POST'])
def status(id):
    if request.method == "GET":
        print(id)
        taskstatus = DeployTask.query.filter_by(id=id).first()  # 找到发布信息
        uid = taskstatus.uid
        nodeinfo = Node.query.filter_by(task=uid).all()
        statulist = []
        for row in nodeinfo:
            nostatus = {'key': str(row.id), "parent": str(row.parent), 'text': str(row.text), 'color': str(row.status)}
            statulist.append(nostatus)
        return jsonify(statulist)
    else:
        taskstatus = DeployTask.query.filter_by(id=id).first()  # 找到发布信息
        return json.dumps({'code': 'init', 'data': status})


@app.route('/add', methods=['GET', 'POST'])
def add():
    if request.method == 'GET':
        return render_template('addserver.html')
    else:
        dic1 = request.form
        # savehost(dic1)
        return redirect(url_for('list'))


@app.route('/project', methods=['GET', 'POST'])
def project():
    if request.method == 'GET':
        pallroject = projects.query.all()
        return render_template('project.html', pallroject=pallroject)
    else:
        dic2 = request.form
        project(dic2)
        return redirect(url_for('project'))


# 根据ID号获取项目的信息
@app.route('/task/<int:id>', methods=['GET', 'POST'])
def task(id):
    if request.method == 'GET':
        project = projects.query.filter_by(id=id).first()  # 根据项目ID拿到项目信息
        tasklist = DeployTask.query.filter_by(project=project.project).all()  # 拿到此项目的发布信息
        return render_template('tasklist.html', tasklist=tasklist, project=project)
    else:
        dic2 = request.form
        addproject(dic2)
        return redirect(url_for('project'))


# 添加发布任务
@app.route('/addtask/<int:id>', methods=['GET', 'POST'])
def addtask(id):
    if request.method == 'GET':
        projectinfo = projects.query.filter_by(id=id).first()
        return render_template('addtask.html', projectinfo=projectinfo)
    else:
        projectinfo = projects.query.filter_by(id=id).first()
        project = projectinfo.project
        env = projectinfo.env
        dic3 = request.form
        date = datetime.datetime.now().strftime('%Y%m%d%H%M%S')
        uid = project + '-' + env + '-' + dic3['tag'] + '-' + date
        addtaskdb(dic3, project, uid)
        return redirect(url_for('project'))


@app.route('/takeinfo/<int:id>', methods=['GET', 'POST'])
def takeinfo(id):
    if request.method == 'GET':
        taskinfo = DeployTask.query.filter_by(id=id).first()
        pro = taskinfo.project
        prinfo = projects.query.filter_by(project=pro).first()
        return render_template('run.html', taskinfo=taskinfo, prinfo=prinfo)


@app.route('/addproject', methods=['GET', 'POST'])
def addproject():
    if request.method == 'GET':
        return render_template('addpro.html')
    else:
        dic2 = request.form
        project(dic2)
        return redirect(url_for('project'))


@app.route('/system', methods=['GET', 'POST'])
def system():
    if request.method == 'GET':
        return render_template('system.html')
    else:
        dic2 = request.form
        project(dic2)
        return redirect(url_for('project'))


@app.route('/addsystem', methods=['GET', 'POST'])
def addsystem():
    if request.method == 'GET':
        return render_template('addsystem.html')
    else:
        addsys = request.form
        print(addsys)
        addsystem(addsys)
        return redirect(url_for('system'))


@app.route('/run/<int:id>', methods=['GET', 'POST'])
def run(id):
    if request.method == 'GET':
        taskinfo = DeployTask.query.filter_by(id=id).first()
        taskinfo.status = "发布中"
        db.session.commit()
        projectinfo = projects.query.filter_by(project=taskinfo.project).first()  # 找到相对应的项目信息
        serverpath = '/root/update/' + date + '/' + '%s' % taskinfo.uid  # 服务器目录
        localpath = '/Users/dayang/PycharmProjects/Devops/codes/' + date
        uploadfile = localpath + '/' + taskinfo.uid + '.zip'  # 上传文件的约绝对地扯
        serverfile = serverpath + '/' + taskinfo.uid + '.zip'  # 上传文件的约绝对地扯
        scriptspath = serverpath + '/' + 'scripts'
        allhost = projects.query.filter_by(project=taskinfo.project).first()
        start = Node(task=taskinfo.uid, text='开始', status='green')
        db.session.add(start)
        db.session.commit()
        t = request.args.get('t')
        if t == "999":
            return url_for('status')
        elif projectinfo.zip == "on":
            print("需要编译")
            return "zip"
        else:
            downloadstatus = "green"
            startid = Node.query.filter_by(task=taskinfo.uid, text='开始').first()
            # 下载代码并打包
            try:
                git(projectinfo, taskinfo)
                try:  # 下载后执行的脚本 ,打包编译
                    os.system("pwd")
                except Exception as e:
                    downloadstatus = "red"
                    logtypes = 0
                    createlogs(uid=taskinfo.uid, types=logtypes, result=e)
                    return "下载后执行失败"
            except Exception as e:  # 如果下载出错
                downloadstatus = "red"
            downloadnode = Node(task=taskinfo.uid, text='下载代码', status=downloadstatus, parent=startid.id)
            db.session.add(downloadnode)
            db.session.commit()
            if downloadstatus == "red":
                return
            else:
                addupnode = Node(task=taskinfo.uid, text="上传文件", parent=downloadnode.id, status="green")
                db.session.add(addupnode)
                db.session.commit()
                upstatus = "green"
                upfile_id = Node.query.filter_by(task=taskinfo.uid, text='上传文件').first()
                allhost = projects.query.filter_by(project=taskinfo.project).first()
                serverslist = allhost.servers.split(",")
                for host in serverslist:
                    infohost = Hosts.query.filter_by(hostname=host).first()
                    try:
                        with SSHProxy(infohost.ipaddr, int(infohost.port), infohost.username,
                                      infohost.passwd) as ssh:
                            result = ssh.command("mkdir -p {0}".format(serverpath))  # 在服务器上创建文件夹
                            ssh.upload(uploadfile, serverfile)
                            result1 = ssh.command('unzip %s -d %s' % (serverfile, serverpath))  # 解压文件
                            # if taskinfo.after_download:
                            #     after_down_status = "green"
                            #     scname = 'after_download.sh'
                            #     scpath = os.path.join(scriptspath, scname)
                            #     ssh.command('sh %s' % scpath)
                            #     try:
                            #         ssh.command(subprocess.check_output("sh {0}".format(scpath), shell=True,
                            #                                             cwd=scriptspath).decode('utf-8'))
                            #     except Exception as e:
                            #         runstatus = "red"
                    except Exception as e:
                        upstatus = "red"
                    uploadstatus = Node(task=taskinfo.uid, text=infohost.hostname, status=upstatus,
                                        parent=upfile_id.id)
                    db.session.add(uploadstatus)
                    db.session.commit()  # "g更新一下数据库状态"
                    print("upstatus:%s" % upstatus)
                    print("225-upstatus:%s%s" % (upstatus, infohost.hostname))
                    if upstatus == "red":
                        print("当前状态:%s" % upstatus)
                        continue
                    return "upstatus"


def addtaskdb(dic3, project, uid):
    addtask1 = DeployTask(uid=uid, project=project, tag=dic3['tag'], versioninfo=dic3['versioninfo'],
                          after_download=dic3['after_download_sc'], before_download=dic3['before_download_sc'],
                          before_deploy_sc=dic3['before_deploy_sc'], after_deploy_sc=dic3['after_deploy_sc'])
    db.session.add(addtask1)
    db.session.commit()


def createlogs(uid, types, result):
    if types == 0:  # 0为系统错误日志
        addlogs = Logs(uid=uid, types=types, result=result)
        db.session.add(addlogs)
        db.session.commit()
    elif types == 1:  # 1为操作日志
        pass


def project(dic2):
    add1 = projects(project=dic2['project'], repo=dic2['repo'], env=dic2['env'], servers=dic2['server'],
                    path=dic2['path'], zip=dic2['zip'])
    db.session.add(add1)
    db.session.commit()


def addsystem(addsys):
    addsys1 = scTemp(title=addsystem['name'], scripts=addsystem['value'])
    db.session.add(addsys1)
    db.session.commit()


if __name__ == '__main__':
    app.run(host='0.0.0.0', port='5000', debug=True)
